package com.macro.mall.es.service.impl;

import com.macro.mall.common.api.EsIndexDto;
import com.macro.mall.es.service.EsIndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;

import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @Author：Minxiao-Hao
 * @Description: 索引管理实现类
 * @name：EsServiceImpl
 * @Date：2024/10/15 20:39
 */
@Service
@Slf4j
public class EsIndexServiceImpl implements EsIndexService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;
    /**
     * 创建索引
     *
     * @param esIndexDto
     */
    @Override
    public void createIndex(EsIndexDto esIndexDto) {

        //查询索引是否存在
        boolean index = exists(esIndexDto.getIndexName());

        if (index) {
            throw new RuntimeException("索引名称已存在,请勿重复创建!!");
        }

        try {
            CreateIndexRequest createIndexRequest = new CreateIndexRequest(esIndexDto.getIndexName());
            // 将 JSON 映射添加到请求中
            String indexMappings = esIndexDto.getIndexMappings();
            log.info("Index mappings: {}", indexMappings);

            // 将 JSON 映射添加到请求中
            if (StringUtils.isNotBlank(esIndexDto.getIndexMappings())) {
                //不加_doc会读取不到索引，不管是7以上的版本还是6都建议加上，避免创建索引时不必要的报错
                createIndexRequest.mapping("_doc",esIndexDto.getIndexMappings(), XContentType.JSON);
            }
            // 发送请求
            restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            log.error("创建索引失败, 异常信息:{}", esIndexDto.getIndexName(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除索引
     *
     * @param indexName 索引名称
     */
    @Override
    public void deleteIndex(String indexName) {
        // 检查索引是否存在
        if (!exists(indexName)) {
            throw new RuntimeException("索引不存在: " + indexName);
        }

        // 创建删除索引请求
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);

        // 执行删除索引操作
        try {
            restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
            log.info("索引删除成功: {}", indexName);
        } catch (Exception e) {
            log.error("删除索引失败, 错误信息: {}", e.getMessage());
            throw new RuntimeException("删除索引失败: " + indexName, e);
        }
    }

    /**
     * 获取索引映射
     *
     * @param indexName 索引名称
     * @return 索引映射信息
     */
    @Override
    public Map<String, Object> getIndex(String indexName) {
        // 检查索引是否存在
        if (!exists(indexName)) {
            throw new RuntimeException("索引不存在: " + indexName);
        }

        // 创建获取索引请求
        GetIndexRequest request = new GetIndexRequest(indexName);

        // 执行获取索引映射操作
        try {
            GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
            log.info("获取索引映射成功: {}", indexName);
            return response.getMappings().get(indexName).sourceAsMap(); // 返回索引映射
        } catch (Exception e) {
            log.error("获取索引映射失败, 错误信息: {}", e.getMessage());
            throw new RuntimeException("获取索引映射失败: " + indexName, e);
        }
    }

    /**
     * 更新索引配置
     *
     * @param esIndexDto 索引信息
     */
    @Override
    public void updateIndex(EsIndexDto esIndexDto) {
        // 检查索引是否存在
        if (!exists(esIndexDto.getIndexName())) {
            throw new RuntimeException("索引不存在: " + esIndexDto.getIndexName());
        }

        // 创建更新索引设置请求
        UpdateSettingsRequest request = new UpdateSettingsRequest(esIndexDto.getIndexName());

        // 更新索引映射
        if (StringUtils.isNotBlank(esIndexDto.getIndexMappings())) {
            request.settings(esIndexDto.getIndexMappings(), XContentType.JSON);
        }

        // 执行更新索引设置操作
        try {
            boolean acknowledged = restHighLevelClient.indices().putSettings(request, RequestOptions.DEFAULT).isAcknowledged();
            if (acknowledged) {
                log.info("索引设置更新成功: {}", esIndexDto.getIndexName());
            } else {
                log.warn("索引设置更新未被确认: {}", esIndexDto.getIndexName());
            }
        } catch (Exception e) {
            log.error("更新索引设置失败, 错误信息: {}", e.getMessage());
            throw new RuntimeException("更新索引设置失败: " + esIndexDto.getIndexName(), e);
        }
    }

    /**
     * 判断索引是否存在
     *
     * @param indexName 索引名称
     * @return 索引是否存在
     */
    @Override
    public boolean exists(String indexName) {
        // 创建获取索引请求
        GetIndexRequest request = new GetIndexRequest(indexName);
        try {
            // 执行获取索引操作并返回索引是否存在
            boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
            log.info("判断索引是否存在: {}, 结果: {}", indexName, exists);
            return exists;
        } catch (Exception e) {
            log.error("判断索引是否存在失败, 错误信息: {}", e.getMessage());
            return false; // 返回判断失败
        }
    }


}
